import {
  ChunkType,
  ComponentPlugin,
  ComponentPluginFactory,
  FileType,
} from '@teleporthq/teleport-types'
import * as types from '@babel/types'

// This plugin is responsible for adding the locale fetcher to the getStaticProps function
// This adds getStaticProps by default to all the pages. If getStaticProps is already present, it will add the locale fetcher to it
// At the moment by default we add this fetcher to all the pages. Because, even if the page is not directly using any locales.
// What happens if one of the component that the page is using is using locales. In that case, the page will need the locales to be fetched.

export const createNextLocaleFetcherPlugin: ComponentPluginFactory<{}> = () => {
  const nextLocaleFetcher: ComponentPlugin = async (structure) => {
    const { chunks } = structure
    if (structure.options.skipI18n) {
      return structure
    }

    const jsxComponent = chunks.find((chunk) => chunk.name === 'jsx-component')
    if (!jsxComponent) {
      return structure
    }

    const getStaticPropsChunk = chunks.find((chunk) => chunk.name === 'getStaticProps')
    const fetcher = types.variableDeclaration('const', [
      types.variableDeclarator(
        types.identifier('messages'),
        types.memberExpression(
          types.awaitExpression(
            types.callExpression(types.import(), [
              types.binaryExpression(
                '+',
                types.binaryExpression(
                  '+',
                  // This path might not be correct. Check with pages that are not in the root pages folder
                  types.stringLiteral('/locales' + '/'),
                  types.memberExpression(types.identifier('context'), types.identifier('locale'))
                ),
                types.stringLiteral('.json')
              ),
            ])
          ),
          types.identifier('default')
        )
      ),
    ])

    if (
      getStaticPropsChunk &&
      typeof getStaticPropsChunk.content === 'object' &&
      'type' in getStaticPropsChunk.content &&
      getStaticPropsChunk.content.type === 'ExportNamedDeclaration'
    ) {
      // Probably getStaticProps is generated by cms, which is already wrapped with try-catch
      const declaration = (getStaticPropsChunk.content as types.ExportNamedDeclaration).declaration
      if (declaration.type !== 'FunctionDeclaration') {
        return structure
      }
      const tryBlock = declaration.body.body[0]
      if (tryBlock.type !== 'TryStatement') {
        return structure
      }
      const returnStatement = tryBlock.block.body.find(
        (item): item is types.ReturnStatement => item.type === 'ReturnStatement'
      )
      if (!returnStatement || returnStatement.argument?.type !== 'ObjectExpression') {
        return structure
      }

      if (
        returnStatement.argument.properties[0]?.type === 'ObjectProperty' &&
        returnStatement.argument.properties[0].value.type === 'ObjectExpression'
      ) {
        tryBlock.block.body.unshift(fetcher)
        returnStatement.argument.properties[0].value.properties.unshift(
          types.objectProperty(
            types.identifier('messages'),
            types.identifier('messages'),
            false,
            true
          )
        )
      }
    } else {
      const exportChunk = types.exportNamedDeclaration(
        types.functionDeclaration(
          types.identifier('getStaticProps'),
          [types.identifier('context')],
          types.blockStatement([
            fetcher,
            types.returnStatement(
              types.objectExpression([
                types.objectProperty(
                  types.identifier('props'),
                  types.objectExpression([
                    types.objectProperty(
                      types.identifier('messages'),
                      types.identifier('messages'),
                      false,
                      true
                    ),
                    types.objectProperty(
                      types.identifier('...context'),
                      types.identifier('...context'),
                      false,
                      true
                    ),
                  ])
                ),
              ])
            ),
          ]),
          false,
          true
        )
      )
      chunks.push({
        name: 'getStaticProps',
        type: ChunkType.AST,
        content: exportChunk,
        fileType: FileType.JS,
        linkAfter: ['jsx-component'],
      })
    }

    return structure
  }

  return nextLocaleFetcher
}
